#include "mytcpsocket.h"
#include "opedb.h"
#include <QMessageBox>
#include <string.h>
#include "protocol.h"
#include "mytcpserver.h"
#include <QDir>

MyTcpSocket::MyTcpSocket() {
    m_upload = false;
    m_timer = new QTimer;

    connect(this, &MyTcpSocket::readyRead, this, [&]() {
        if (!m_upload) {  //不是上传文件的状态
            //qDebug() << this->bytesAvailable();
            uint total_len = 0;
            this->read((char*)&total_len, sizeof(total_len));
            uint PDUmsg_len = total_len - sizeof(PDU);
            PDU* pdu = makePDU(PDUmsg_len);
            this->read((char*)pdu+sizeof(uint), total_len - sizeof(uint));

            //接收数据
            PDU* req_pdu;
            bool write_flag = true;  //为true 才发送PDU;
            switch (pdu->uiMsgType) {
            case ENUM_MSG_TYPE_REGIST_REQUEST: {
                char name[32] = {'\0'};
                char pwd[32] = {'\0'};
                strncpy(name, pdu->caData, 32);
                strncpy(pwd, pdu->caData+32, 32);

                //qDebug() << "注册：" << name << pwd;
                //把用户名，密码插入数据库：
                req_pdu = makePDU(0); //数据部分为0
                if (OpeDB::getInstence().handle_regist(name, pwd) ) { //注册成功
                    strcpy(req_pdu->caData, REGIST_OK);
                    //创建文件夹
                    QDir dir;
                    bool ret = dir.mkdir(QString("./%1").arg(name));
                    if (!ret) qDebug() << "创建文件夹失败";
                } else {
                    strcpy(req_pdu->caData, REGIST_FAILED);
                }
                //qDebug() << req_pdu->caData;
                req_pdu->uiMsgType = ENUM_MSG_TYPE_REGIST_RESPOND;

                break;
            }
            case ENUM_MSG_TYPE_LOGIN_REQUEST: {
                char name[32] = {'\0'};
                char pwd[32] = {'\0'};
                strncpy(name, pdu->caData, 32);
                strncpy(pwd, pdu->caData+32, 32);

                req_pdu = makePDU(0); //数据部分为0
                if (OpeDB::getInstence().handle_login(name, pwd) ) { //登陆成功
                    strcpy(req_pdu->caData, LOGIN_OK);
                    m_name = name; //保存名字, 等注销的时候, 把online置为0
                } else {
                    strcpy(req_pdu->caData, LOGIN_FAILED);
                }
                //qDebug() << req_pdu->caData;
                req_pdu->uiMsgType = ENUM_MSG_TYPE_LOGIN_RESPOND;

                break;
            }
            case ENUM_MSG_TYPE_SHOW_ONLINE_REQUEST: {
                QStringList names = OpeDB::getInstence().handle_show_online();
                uint msg_len = names.size()*32;
                req_pdu = makePDU(msg_len);

                req_pdu->uiMsgType = ENUM_MSG_TYPE_SHOW_ONLINE_RESPOND;
                for (int i = 0; i < names.size(); i++) {
                    memcpy((char*)(req_pdu->caMsg)+i*32,
                           names[i].toStdString().c_str(),
                           names[i].size());
                }

                break;
            }
            case ENUM_MSG_TYPE_SEARCH_REQUEST: {
                req_pdu = makePDU(0);
                int status = OpeDB::getInstence().handle_search_user(pdu->caData);
                if (status == -1)
                    strcpy(req_pdu->caData, NO_THIS_PEOPLE);
                else if (status == 1)
                    strcpy(req_pdu->caData, PEOPLE_ONLINE);
                else
                    strcpy(req_pdu->caData, PEOPLE_NOT_ONLINE);

                // qDebug() << status;
                req_pdu->uiMsgType = ENUM_MSG_TYPE_SEARCH_RESPOND;
                break;
            }
            case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST: {
                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
                char user_name[32] = {'\0'};
                char my_name[32] = {'\0'};
                strncpy(user_name, pdu->caData, 32);
                strncpy(my_name, pdu->caData+32, 32);
                // qDebug() << user_name << "-" << my_name;
                int ret = OpeDB::getInstence().handle_add_friend(my_name, user_name);
                /*
handle_add_friend返回值:
参数的名字为空: -1;
已经是好友: 0;
对方在线: 1;
对方不在线: 2;
对方不存在: 3
*/
                if (ret == -1) {
                    strcpy(req_pdu->caData, NAME_IS_NULL);
                } else if (ret == 0) {
                    strcpy(req_pdu->caData, ALREADY_FRIEND);
                } else if (ret == 1) { //对方在线, 加好友
                    free(req_pdu); req_pdu = NULL;
                    MyTcpServer::getInstance().resend(user_name, pdu); //转发
                    write_flag = false;
                } else if (ret == 2) {
                    strcpy(req_pdu->caData, PEOPLE_NOT_ONLINE);
                } else if (ret == 3) {
                    strcpy(req_pdu->caData, NO_THIS_PEOPLE);
                }

                break;
            }
            case ENUM_MSG_TYPE_ADD_FRIEND_AGREE: { //同意添加好友请求
                char user_name[32] = {'\0'};
                char my_name[32] = {'\0'};
                strncpy(my_name, pdu->caData, 32);
                strncpy(user_name, pdu->caData+32, 32);
                OpeDB::getInstence().handle_add_friend_agree(my_name, user_name);
                write_flag = false;
                break;
            }
            case ENUM_MSG_TYPE_FLUSH_FRIEND_REQUEST: {
                QStringList names = OpeDB::getInstence().handle_flush_friend(pdu->caData);
                // qDebug() << names;
                uint msg_len = names.size()*32;
                req_pdu = makePDU(msg_len);

                req_pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIEND_RESPOND;
                for (int i = 0; i < names.size(); i++) {
                    memcpy((char*)(req_pdu->caMsg)+i*32,
                           names[i].toStdString().c_str(),
                           names[i].size());
                }

                break;
            }
            case ENUM_MSG_TYPE_DEL_FRIEND_REQUEST: {
                char user_name[32] = {'\0'};
                char my_name[32] = {'\0'};
                strncpy(user_name, pdu->caData, 32);
                strncpy(my_name, pdu->caData+32, 32);
                // qDebug() << user_name << "-" << my_name;
                int ret = OpeDB::getInstence().handle_del_friend(my_name, user_name);

                //回复给主动删好友的客户端
                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_DEL_FRIEND_RESPOND;
                strcpy(req_pdu->caData, DEL_FRIEND_OK);

                //给被删好友的转发一个提示
                MyTcpServer::getInstance().resend(user_name, pdu); //转发

                break;
            }
            case ENUM_MSG_TYPE_SEND_MSG_REQUEST: { //私聊
                char user_name[32] = {'\0'};
                strncpy(user_name, pdu->caData+32, 32);
                // req_pdu = makePDU(0);
                //转发
                MyTcpServer::getInstance().resend(user_name, pdu); //转发
                write_flag = false;
                break;
            }
            case ENUM_MSG_TYPE_GROUP_CHAT_REQUEST: {
                //先得到在线好友列表
                QStringList names = OpeDB::getInstence().handle_flush_friend(pdu->caData);
                //转发
                for (auto& str : names) { //循环转发给在线好友
                    // qDebug() << str;
                    MyTcpServer::getInstance().resend(str.toStdString().c_str(), pdu); //转发给在线好友
                }
                write_flag = false;
                break;
            }
            case ENUM_MSG_TYPE_CREATE_DIR_REQUEST: {
                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_CREATE_DIR_RESPOND;
                QDir dir;
                QString curDir = QString("%1").arg((char*)pdu->caMsg);
                bool ret = dir.exists(curDir);
                // qDebug() << "-------->" << ret;
                if (ret) { //当前目录存在
                    char create_dir[32] = {'\0'};
                    strncpy(create_dir, pdu->caData+32, 32);
                    QString new_dir = QString("%1/%2").arg(curDir).arg(create_dir);
                    ret = dir.exists(new_dir);
                    // qDebug() << "new create dir:" << new_dir;
                    // qDebug() << "---------->" << ret2;
                    if (!ret) {
                        dir.mkdir(new_dir);
                        strcpy(req_pdu->caData, CREATE_DIR_OK);
                    } else {
                        strcpy(req_pdu->caData, DIR_ALREADY_EXISTS);
                    }

                } else { //当前目录不存在
                    strcpy(req_pdu->caData, CREATE_DIR_FAILED);
                }
                break;
            }
            case ENUM_MSG_TYPE_FLUSH_FILE_REQUEST: {
                QString cur_path = QString("%1").arg((char*)pdu->caMsg);
                // qDebug() << cur_path;
                QFileInfo file_info(cur_path);
                //如果cur_path是文件, 或者文件不存在, 就不用打开了
                if (file_info.isFile() || !QFileInfo::exists(cur_path)) {
                    // qDebug() << "是文件:" << file_info.isFile();
                    write_flag = false;
                    break;
                }

                QDir dir(cur_path);
                QFileInfoList file_info_list = dir.entryInfoList();
                int file_count = file_info_list.size();

                req_pdu = makePDU(sizeof(FileInfo)*file_count);
                FileInfo *p_file_info = NULL;
                QString file_name;
                for (int i = 0; i < file_count; i++) {
                    // qDebug() << file_info_list[i].fileName() << ", "
                    //          << file_info_list[i].size();
                    p_file_info = (FileInfo*)(req_pdu->caMsg)+i;
                    file_name = file_info_list[i].fileName();
                    memcpy(p_file_info->file_name, file_name.toStdString().c_str(), file_name.size());
                    if (file_info_list[i].isDir()) {
                        p_file_info->file_type = 0;
                    } else if (file_info_list[i].isFile()){
                        p_file_info->file_type = 1;
                    }
                }

                strcpy(req_pdu->caData, FLUSH_FILE_OK);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FILE_RESPOND;
                break;
            }
            case ENUM_MSG_TYPE_GO_BACK_DIR_REQUEST: {
                QString cur_path = QString("%1").arg((char*)pdu->caMsg);
                // qDebug() << cur_path;
                QFileInfo file_info(cur_path);
                //如果cur_path是文件, 或者文件不存在, 就不用打开了
                if (file_info.isFile() || !QFileInfo::exists(cur_path)) {
                    // qDebug() << "是文件:" << file_info.isFile();
                    write_flag = false;
                    break;
                }

                QDir dir(cur_path);
                QFileInfoList file_info_list = dir.entryInfoList();
                int file_count = file_info_list.size();

                req_pdu = makePDU(sizeof(FileInfo)*file_count);
                FileInfo *p_file_info = NULL;
                QString file_name;
                for (int i = 0; i < file_count; i++) {
                    // qDebug() << file_info_list[i].fileName() << ", "
                    //          << file_info_list[i].size();
                    p_file_info = (FileInfo*)(req_pdu->caMsg)+i;
                    file_name = file_info_list[i].fileName();
                    memcpy(p_file_info->file_name, file_name.toStdString().c_str(), file_name.size());
                    if (file_info_list[i].isDir()) {
                        p_file_info->file_type = 0;
                    } else if (file_info_list[i].isFile()){
                        p_file_info->file_type = 1;
                    }
                }

                strcpy(req_pdu->caData, FLUSH_FILE_OK);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_GO_BACK_DIR_RESPOND;
                break;
            }
            case ENUM_MSG_TYPE_DEL_FILE_REQUEST: {
                QString path = QString("%1/%2").arg((char*)pdu->caMsg).arg(pdu->caData);
                qDebug() << path;

                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_DEL_FILE_RESPOND;
                    // "." 和".."特殊处理
                bool ret = false;
                if (path.isEmpty() || !QDir().exists(path)) {
                    strcpy(req_pdu->caData, DEL_FILE_FAILED_NOT_EXISTS);
                    break;
                }

                QFileInfo file_info(path);
                if (file_info.isDir()) {
                    // qDebug() << "is dir?" << file_info.isDir();
                    QDir dir;
                    dir.setPath(path);
                    ret = dir.removeRecursively(); //删除文件夹, 包括里面的文件
                } else if (file_info.isFile()) {
                    // qDebug() << "is file?" << file_info.isFile();
                    ret = QFile::remove(path);
                }

                if (ret) {
                    strcpy(req_pdu->caData, DEL_FILE_OK);
                } else {
                    strcpy(req_pdu->caData, DEL_FILE_FAILED);
                }
                // req_pdu->printPDU();
                break;
            }
            case ENUM_MSG_TYPE_RENAME_FILE_REQUEST: {
                QString old_path = QString("%1/%2").arg((char*)pdu->caMsg).arg(pdu->caData);
                QString new_path = QString("%1/%2").arg((char*)pdu->caMsg).arg(pdu->caData+32);
                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_RENAME_FILE_RESPOND;
                // qDebug() << "old_path:" << old_path << endl
                //          << "new_path:" << new_path;

                bool ret = QFileInfo::exists(old_path);
                bool ret2 = QFileInfo::exists(new_path);
                if (ret2) {  //新的文件名已经存在
                    strcpy(req_pdu->caData, NEW_NAME_FILE_FAILED_ALREADY_EXISTS);
                    break;
                }
                if (ret) { //旧的文件名存在
                    QDir dir;
                    if (dir.rename(old_path, new_path) ) {
                        strcpy(req_pdu->caData, RENAME_FILE_OK);
                    } else {
                        strcpy(req_pdu->caData, RENAME_FILE_FAILED);
                    }
                } else { //当前文件不存在
                    strcpy(req_pdu->caData, RENAME_FILE_FAILED_NO_EXISTS);
                }
                // req_pdu->printPDU();
                break;
            }
            case ENUM_MSG_TYPE_ENTER_FOLDER_REQUEST: {
                QString pre_path = QString("%1").arg((char*)pdu->caMsg);
                QString dir_name = QString("%1").arg(pdu->caData);
                QString cur_path = pre_path + "/" + dir_name;
                qDebug() << cur_path;
                QFileInfo file_info(cur_path);
                //如果cur_path是文件, 或者文件不存在, 就不用打开了
                if (file_info.isFile() || !QFileInfo::exists(cur_path)) {
                    // qDebug() << "是文件:" << file_info.isFile();
                    req_pdu = makePDU(0);
                    strcpy(req_pdu->caData, ENTER_DIR_FAILED);
                    req_pdu->uiMsgType = ENUM_MSG_TYPE_ENTER_FOLDER_RESPOND;
                    break;
                }

                QDir dir(cur_path);
                QFileInfoList file_info_list = dir.entryInfoList();
                int file_count = file_info_list.size();

                req_pdu = makePDU(sizeof(FileInfo)*file_count);
                FileInfo *p_file_info = NULL;
                QString file_name;
                for (int i = 0; i < file_count; i++) {
                    // qDebug() << file_info_list[i].fileName() << ", "
                    //          << file_info_list[i].size();
                    p_file_info = (FileInfo*)(req_pdu->caMsg)+i;
                    file_name = file_info_list[i].fileName();
                    memcpy(p_file_info->file_name, file_name.toStdString().c_str(), file_name.size());
                    if (file_info_list[i].isDir()) {
                        p_file_info->file_type = 0;
                    } else if (file_info_list[i].isFile()){
                        p_file_info->file_type = 1;
                    }
                }

                strcpy(req_pdu->caData, FLUSH_FILE_OK);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FILE_RESPOND;
                break;
            }
            case ENUM_MSG_TYPE_UPLOAD_FILE_REQUEST: {
                // pdu->printPDU();
                write_flag = false;
                char file_name[32] = {'\0'};
                qint64 file_size = 0;
                sscanf(pdu->caData, "%s %lld", file_name, &file_size);
                QString path = QString("%1/%2").arg((char*)pdu->caMsg).arg(file_name);
                // qDebug() << "server upload file:" << path;

                m_file.setFileName(path);
                //以只写的方式打开文件, 若文件不存在, 则会自动创建文件
                if (m_file.open(QIODevice::WriteOnly)) {
                    m_upload= true;
                    m_total = file_size;
                    m_recved = 0;
                }
                break;
            }
            case ENUM_MSG_TYPE_DOWNLOAD_FILE_REQUEST: {
                QString pre_path = QString("%1").arg((char*)pdu->caMsg);
                QString dir_name = QString("%1").arg(pdu->caData);
                QString cur_path = pre_path + "/" + dir_name;
                // qDebug() << cur_path;
                QFileInfo file_info(cur_path);
                qint64 file_size = file_info.size();
                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_DOWNLOAD_FILE_RESPOND;
                sprintf((char*)req_pdu->caData, "%s %lld", pdu->caData, file_size);
                write((char*)req_pdu, req_pdu->uiPDULen); //socket 发送
                // req_pdu->printPDU();
                free(req_pdu); req_pdu = NULL;
                write_flag = false;
                m_file.setFileName(cur_path);
                m_timer->start(1000); //1000毫秒

                break;
            }
            case ENUM_MSG_TYPE_SHARE_FILE_REQUEST: {
                char send_name[32] = {'\0'};
                int num = 0;
                sscanf(pdu->caData, "%s%d", send_name, &num);
                // qDebug() << "send_name = " << send_name << " ," << "num = " << num << endl;
                int size = num*32;
                req_pdu = makePDU(pdu->uiMsgLen-size + 1);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_NOTE;
                strcpy(req_pdu->caData, send_name);
                memcpy(req_pdu->caMsg, (char*)(pdu->caMsg)+size, pdu->uiMsgLen-size);

                char recv_name[32] = {'\0'};
                for (int i = 0; i < num; i++) {
                    memcpy(recv_name, (char*)(pdu->caMsg)+i*32, 32);
                    MyTcpServer::getInstance().resend(recv_name, req_pdu);
                }
                write_flag = false;
                free(req_pdu); req_pdu = NULL;

                req_pdu = makePDU(0);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_RESPOND;
                strcpy(req_pdu->caData, SHARE_FILE_OK);
                write((char*)req_pdu, req_pdu->uiPDULen);
                free(req_pdu); req_pdu = NULL;
                break;
            }
            case ENUM_MSG_TYPE_SHARE_FILE_NOTE_RESPOND: {
                QString recv_path = QString("./%1").arg(pdu->caData); //把文件放在用户的一级目录下
                QString share_file_path = QString("%1").arg((char*)pdu->caMsg);
                qDebug() << "recv_path = " << recv_path << ", share_file_path = " << share_file_path;

                int index = share_file_path.lastIndexOf('/');
                qDebug() << "index = " << index;
                QString file_name = share_file_path.right(share_file_path.size() - index-1);
                recv_path = recv_path + '/' + file_name;
                qDebug() << "recv_path = " << recv_path;

                QFileInfo fileInfo(share_file_path);
                if (fileInfo.isFile()) {
                    QFile::copy(share_file_path, recv_path);
                } else if (fileInfo.isDir()) {
                    this->copy_dir(share_file_path, recv_path); //递归拷贝目录文件
                }
                write_flag = false;
            }
            case ENUM_MSG_TYPE_MOVE_FILE_REQUEST: {
                /*
        sprintf(pdu->caData, "%d %d %s", src_len, dest_len, m_move_file_name.toStdString().c_str());
        strncpy((char*)pdu->caMsg, m_move_file_path.toStdString().c_str(), m_move_file_path.size());
        strncpy((char*)pdu->caMsg+src_len+1, m_move_file_dest_path.toStdString().c_str(), m_move_file_dest_path.size());
*/
                char file_name[32] = {'\0'};
                int src_len = 0, dest_len = 0;
                sscanf(pdu->caData, "%d %d %s", &src_len, &dest_len, file_name);
                qDebug() << "src_len = " << src_len << ", dest_len = " << dest_len
                         << ", file_name = " << file_name;

                char move_file_path[src_len+1];
                char move_file_dest_path[dest_len+1+32]; //+32:加上文件名
                memset(move_file_path, '\0', src_len+1);
                memset(move_file_dest_path, '\0', dest_len+1+32);

                strncpy(move_file_path, (char*)pdu->caMsg, src_len);
                strncpy(move_file_dest_path, (char*)pdu->caMsg + src_len+1, dest_len);
                qDebug() << "move_file_path = " << move_file_path
                         << ", move_file_dest_path = " << move_file_dest_path;

                bool ret = false;
                QFileInfo file_info(move_file_dest_path);
                if (file_info.isDir()) {
                    strcat(move_file_dest_path, "/");
                    strcat(move_file_dest_path, file_name);
                    ret = QFile::rename(move_file_path, move_file_dest_path);
                }

                req_pdu = makePDU(0);
                if (ret)
                    strcpy(req_pdu->caData, MOVE_FILE_OK);
                else strcpy(req_pdu->caData, MOVE_FILE_FAIL);
                req_pdu->uiMsgType = ENUM_MSG_TYPE_MOVE_FILE_RESPOND;

                break;
            }
            default:
                write_flag = false;
                break;
            }
            if (write_flag) {
                write((char*)req_pdu, req_pdu->uiPDULen); //socket 发送
                // req_pdu->printPDU();
                free(req_pdu); req_pdu = NULL;
            }

            free(pdu); pdu = NULL;

        } else { //上传文件
            qDebug() << "sever 上传----------------------";
            PDU* res_pdu = NULL;
            res_pdu = makePDU(0);
            res_pdu->uiMsgType = ENUM_MSG_TYPE_UPLOAD_FILE_RESPOND;

            QByteArray buff = readAll();
            m_file.write(buff);
            m_recved += buff.size();
            // qDebug() << "buff = " << buff.toStdString().c_str();
            if (m_total == m_recved) { //数据接收完毕
                m_file.close();
                m_upload = false;
                strcpy(res_pdu->caData, UPLOAD_FILE_OK);
                write((char*)res_pdu, res_pdu->uiPDULen); //socket 发送
                // req_pdu->printPDU();
                free(res_pdu); res_pdu = NULL;
            } else if (m_total < m_recved) { //数据接收失败
                m_file.close();
                m_upload = false;
                strcpy(res_pdu->caData, UPLOAD_FILE_FAIL);
                write((char*)res_pdu, res_pdu->uiPDULen); //socket 发送
                // req_pdu->printPDU();
                free(res_pdu); res_pdu = NULL;
            }

        }
    });

    //刚发完文件的信息, 不能接着就发送文件, 可能会出现粘包的现象, 需要添加一个定时器, 过了多少秒后才开始发送
    connect(m_timer, &QTimer::timeout, this, [&]() {
        m_timer->stop();
        if (!m_file.open(QIODevice::ReadOnly) ) {
            QMessageBox::warning(NULL, "打开文件", "打开文件失败");
            return;
        }

        // 有人曾经做过实验, 缓冲区大小为`4096`, 它的读写效率较高
        char* buf = new char[4096];
        qint64 ret = 0;
        while (1) {
            ret = m_file.read(buf, 4096);
            qDebug() << "ret = " << ret;
            if (ret > 0 && ret <= 4096) {
                write(buf, ret);
            } else if (ret == 0) { //读到文件末尾
                break;
            } else {
                QMessageBox::warning(NULL, "发送文件", "服务器发送文件失败");
                break;
            }
        }

        m_file.close();
        delete []buf;
        buf = NULL;
    });

    //当socket断开时
    connect(this, &QTcpSocket::disconnected, this, [&]() {
        OpeDB::getInstence().handle_logout(m_name.toStdString().c_str());
        emit logout(this);
    });
}

void MyTcpSocket::copy_dir(QString src_dir, QString dest_dir)
{
    QDir dir;
    dir.mkdir(dest_dir);

    dir.setPath(src_dir);
    QFileInfoList file_info_list = dir.entryInfoList();
    int file_count = file_info_list.size();

    QString src_tmp, dest_tmp;
    for (int i = 0; i < file_count; i++) {
        qDebug() << "file_info_list[i].fileName() = " << file_info_list[i].fileName();
        if (file_info_list[i].fileName() == "." ||
            file_info_list[i].fileName() == "..") continue;
        src_tmp = src_dir + "/" + file_info_list[i].fileName();
        dest_tmp = dest_dir + "/" + file_info_list[i].fileName();

        if (file_info_list[i].isDir()) {
            this->copy_dir(src_tmp, dest_tmp); //递归调用
        } else if (file_info_list[i].isFile()){
            QFile::copy(src_tmp, dest_tmp);
        }
    }

}
